<?php
/**
 * Note: *
 * Date: 2021/7/23
 */

namespace App\Http\Controllers\Admin;

use App\Jobs\MakeApk;
use App\Jobs\UploadApk;
use App\Models\Game\Center\Apk;
use App\Models\Game\Center\AppSource;
use Carbon\Carbon;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\File;
use Illuminate\Validation\Rule;

class ApkController extends CurdController
{
    protected string $classModel = Apk::class;

    protected array $searchFields = [
        'source',
        'base_apk',
        'status' => self::FIELD_TYPE_NUMERIC,
        'name' => self::FIELD_TYPE_LIKE,
    ];

    protected array $orderFields = [
        'source' => 'desc',
    ];

    public function index(Request $request)
    {
        if (is_numeric($request->source_type) && !$request->source) {
            $request->source = AppSource::ofFieldNumeric('type', $request->source_type)->pluck('id')->all();
        }
        return $this->myIndex();
    }

    /**
     * @param Request $request
     */
    public function storeBefore(Request $request)
    {
        $request->validate([
            'source' => [
                'required',
                Rule::unique('gameCenter.apks'),
            ],
            'base_apk' => 'required|string',
            // 'domain_group_name' => 'required|string',
        ]);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->storeBefore($request);

        $apk = new Apk();
        return $this->storeModel($request, $apk);
    }

    /**
     * @param Request $request
     */
    public function updateBefore(Request $request)
    {
        $request->validate([
            'source' => [
                'required',
                Rule::unique('gameCenter.apks')->ignore($request->id),
            ],
            'base_apk' => 'required|string',
            // 'domain_group_name' => 'required|string',
        ]);
    }

    /**
     * 更新
     * @param Request $request
     * @param Apk $apk
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function update(Request $request, Apk $apk)
    {
        $this->updateBefore($request);

        return $this->storeModel($request, $apk);
    }

    /**
     * 保存
     * @param Request $request
     * @param Apk $apk
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    private function storeModel(Request $request, Apk $apk)
    {
        $apk->fill($request->all());
        $apk->domain_platform = collect(config('game.safeDomains'))->random();
        $apk->name = config('game.apk.namePrefix'). $apk->source . '.apk';;
        // if (!Str::of($apk->name)->endsWith('.apk')) $apk->name .= '.apk';
        $apk->path = '';
        $apk->status = Apk::STATUS_INIT;
        if (!$apk->save()) {
            return responseException(__('web.failed'));
        }
        // 生成APK 并上传到CDN
        MakeApk::withChain([
            new UploadApk($apk)
        ])->dispatch($apk);

        return responseMessage(__('web.success'));
    }

    /**
     * 批量处理
     * @param Request $request
     * @return Application|ResponseFactory|Response
     */
    public function batch(Request $request)
    {
        $sources = $request->sources;
        foreach ($sources as $source) {
            $apk = Apk::whereSource($source)->updateOrCreate([
                'source' => $source,
            ], [
                'base_apk' => $request->base_apk,
                'domain_platform' => collect(config('game.safeDomains'))->random(),
                'name' => config('game.apk.namePrefix'). $source . '.apk',
                'path' => '',
                'status' => Apk::STATUS_INIT,
            ]);

            // 生成APK 并上传到CDN
            MakeApk::withChain([
                new UploadApk($apk)
            ])->dispatch($apk);
        }
        return responseMessage(__('web.success'));
    }

    /**
     * 基准包(母包)列表
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function base()
    {
        $allFiles = File::allFiles(config('game.apk.basePath'));
        $files = [];
        foreach ($allFiles as $file) {
            if (strtolower($file->getExtension()) !== 'apk') continue;
            $files[] = [
                'name' => $file->getFilename(),
                'path' => $file->getRealPath(),
                'size' => humanFilesize($file->getSize()),
                'mtime' => Carbon::createFromTimestamp($file->getMTime())->toDateTimeString(),
                'ctime' => Carbon::createFromTimestamp($file->getCTime())->toDateTimeString(),
            ];
        }
        usort($files, function($a, $b) {
            return $a['mtime'] > $b['mtime'] ? -1 : 1;
        });
        return responseData($files);
    }

    /**
     * 上传成功
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function uploadBase(Request $request)
    {
        sleep(0);
        if (!$request->file('apk')->isValid()) {
            return responseException('文件完整性检查失败');
        }
        if ($request->file('apk')->getClientOriginalExtension() !== 'apk') {
            return responseException('文件类型错误');
        }

        $storeFileName = $request->file('apk')->getClientOriginalName();
        // 删除旧包
        File::delete(config('game.apk.basePath') . $storeFileName);

        $path = $request->file('apk')->move(config('game.apk.basePath'), $storeFileName)->getPath();
        return responseMessage($path);
    }

    /**
     * 删除母包文件
     * @param $name
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function deleteBase($name)
    {
        $filepath = config('game.apk.basePath') . $name;
        $exists = File::exists($filepath);
        if (!$exists) return responseMessage('文件不存在');
        if (!File::delete($filepath)) {
            return responseMessage('文件不存在');
        }
        return responseMessage();
    }
}
